NIUHE

日々私たちが过ごしている日常というのは、実は奇迹の连続なのかもしれんな

记录:在 Docker 上配置 PHP 应用

什么是Docker docker的英文本意是码头工人,也就是搬运工,这种搬运工搬运的是集装箱(Container),集装箱里面装的可不是商品货物,而是任意类型的App,Docker把App(叫Payload)装在Container内,通过Linux Container技术的包装将App变成一种标准化的、可移植的、自管理的组件,这种组件可以在你的latop上开发、调试、运行,最终非常方便和一致地运行在production环境下。

起因是腾讯云的学生审核通过了,然后就花一块钱买了个服务器,就想在腾讯云上也配置下我的(前)博客,但是又不想每次都重新配置环境,于是就想到了Docker,折腾了两三天网站总算是可以跑了,这里记录一下踩坑过程。

Docker的核心底层技术是LXC(Linux Container),Docker在其上面加了薄薄的一层,添加了许多有用的功能。这篇stackoverflow上的问题和答案很好地诠释了Docker和LXC的区别,能够让你更好的了解什么是Docker, 简单翻译下就是以下几点: * Docker提供了一种可移植的配置标准化机制,允许你一致性地在不同的机器上运行同一个Container;而LXC本身可能因为不同机器的不同配置而无法方便地移植运行; Docker以App为中心,为应用的部署做了很多优化,而LXC的帮助脚本主要是聚焦于如何机器启动地更快和耗更少的内存; * Docker为App提供了一种自动化构建机制(Dockerfile),包括打包,基础设施依赖管理和安装等等; * Docker提供了一种类似git的Container版本化的机制,允许你对你创建过的容器进行版本管理,依靠这种机制,你还可以下载别人创建的Container,甚至像git那样进行合并; * Docker Container是可重用的,依赖于版本化机制,你很容易重用别人的Container(叫Image),作为基础版本进行扩展; * Docker Container是可共享的,有点类似github一样,* Docker有自己的INDEX,你可以创建自己的Docker用户并上传和下载Docker Image; * Docker提供了很多的工具链,形成了一个生态系统;这些工具的目标是自动化、个性化和集成化,包括对PAAS平台的支持等;


我之前其实是买过一本Docker的书的,但是还没来得及怎么看,这次突然要用就赶紧翻了翻,也Google了一下,发现了这个网站 : Docker —— 从入门到实践,结果发现书里的内容和这里基本一样,连名字也差不多,早知道就不买书了。

就这样开始了学习Docker之旅。

我的网站环境是nginx+php+mysql,鉴于数据库还用原来服务器上的就好,所以只需要配置nginx与php。

这里有两个选项: * nginx和php放到一个docker里 * 把nginx和php分开放到两个docker里

前者明显看起来简单一些,因为不涉及容器互联等问题还省事,但其实这种将所有服务放在一个容器内的模式有个形象的非官方称呼:Fat Container。与之相对的是将服务分拆到容器的模式。从Docker的设计可以看到,构建镜像的过程中可以指定唯一一个容器启动的指令,因此Docker天然适合一个容器只运行一种服务,而这也是官方更推崇的。

由于我一开始并不知道一个docker只能运行一个服务,所以我选了第一种方案,然后就多踩了一个大坑。

当时遇到这么一个有趣的现象:我用Dockerfile创建镜像,Dockerfile最后包含这么两条启动服务的命令

1
2
CMD ["nginx"]
CMD ["php-fpm"]

nginx天生就是后台服务,而php-fpm一这种方式可以前台运行,看起来这种组合挺好,容器启动之后也不会立刻终止,而是一直在运行,但是访问不了网站!!

这是为什么呢? 因为nginx在最后那个容器里没有启动,具体为什么没有启动我也不是很清楚,这也就是说Docker天然适合一个容器只运行一种服务的原因吧。可是如果只保留nginx的话,也会因为它是后台运行所以容器刚运行就会停止。

然后我就好奇别人的nginx是怎么运行的。我就看了看nginx的官方镜像,再它的dockerfile最后写的是:

1
CMD ["nginx", "-g", "daemon off;"]

查了查然后知道通过这个参数可以让nginx前台运行,而不会使容器直接停止。

然后我就把Dockerfile修改成这样:

1
2
CMD ["php-fpm"]
CMD ["nginx", "-g", "daemon off;"]

大家应该也看出来了,这样就喜闻乐见地解析不了php了。

接着我就好奇别人的集成好多服务的docker是怎么启动的,google到了几个这样的应用,然后就发现了supervisord,这个东东是一个进程管理器,可以完美解决上述问题,只需一个配置文件:

1
2
3
4
5
6
7
8
[supervisord]
nodaemon=true

[program:php-fpm]
command=php-fpm

[program:nginx]
command=nginx

配置和启动命令就可以写成:

1
2
ADD ./supervisord.conf /etc/supervisord.conf
CMD ["supervisord"]

这样困扰我好久的问题就解决了。不过这只是我踩到的总多坑的其中之一,算是比较大的一个,也是稍微有点分享价值的一个,相比这个问题的解决方案而言,解决这个问题的过程更有价值一些吧,故在此记录一下。

ps : 还有个小坑也值得注意一下,我用centos7作为基础镜像,通过yum安装的php不自带mysqli模块,需要手动安装RUN yum install -y php-mysqli,这个当时找问题也找了好久。

参考 http://dockerpool.com/static/books/docker_practice/index.html http://tech.uc.cn/?p=2726 http://avnpc.com/pages/build-php-develop-env-by-docker

Powered by Hexo and Theme by Hacker
© 2019 NIUHE